package cn.est.service.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密是一种常见的加密方式，经常用在保存用户密码和关键信息上。
 * MD5加密全程是Message-Digest Algoorithm 5（信息-摘要算法），它对信息进行摘要采集，
 * 再通过一定的位运算，最终获取加密后的MD5字符串。
 * MD5是一个单向密码体制，即从明文到密文的不可逆映射，只有加密过程没有解密过程，
 * 哈希函数可以将任意长度的输入经过变化后得到固定长度的输出，
 * 这个固定长度的输出称为原消息的散列或消息映射。
 * 注：通过自定义加解密算法可以实现加密和解密。
 */
public class MD5Utils {

	/**
	 * md5加密
	 * @param sourceStr
	 * @return
	 */
	public static String MD5(String sourceStr) {
		String result = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(sourceStr.getBytes());
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			result = buf.toString();
		} catch (NoSuchAlgorithmException e) {
			System.out.println(e);
		}
		return result;
	}

	/*
	MD5加密
	 */
	public static String encrypt(String inStr){
		StringBuffer hexValue = new StringBuffer();
		MessageDigest md5 = null;
		try{
			/*
			生成一个MD5加密计算摘要.此为MD5核心。
			 */
			md5 = MessageDigest.getInstance("MD5");
			char[] charArray = inStr.toCharArray();
			byte[] byteArray = new byte[charArray.length];

			for (int i = 0; i < charArray.length; i++){
				byteArray[i] = (byte) charArray[i];
			}

			byte[] md5Bytes = md5.digest(byteArray);

			for (int i = 0; i < md5Bytes.length; i++){
				/*
				&表示按位与,只有两个位同时为1,才能得到1,
				0x代表16进制数,0xff表示的数二进制1111 1111 ,占一个字节.
				前面数据与0xff进行&操作后,最低8位不会发生变化。
				 */
				int val = ((int) md5Bytes[i]) & 0xff;
				if (val < 16){
					hexValue.append("0");
				}else{
					//若val>=16,则将其转换为十六进制数追加入hexValue
					hexValue.append(Integer.toHexString(val));
				}
			}
		}catch (Exception e){
			System.out.println(e.toString());
			e.printStackTrace();
			return "";
		}
		return hexValue.toString();
	}

	public static String decrypt(String inStr){
		char[] a = inStr.toCharArray();
		for (int i = 0; i < a.length; i++){
			/*
			异或运算。字符t的二进制：0101 0100
			 */
			a[i] = (char) (a[i] ^ 't');
		}
		String s = new String(a);
		return s;
	}

	public static void main(String[] args) {
		String info="admin例&";
		System.out.println("原始： " + info);
		System.out.println("加密后：" + encrypt(info));
		System.out.println("一次解密："+ decrypt(info));
		System.out.println("连续二次解密： " + decrypt(decrypt(info)));
	}


}
